﻿using System;
using System.Collections.Generic;
using System.Diagnostics;


namespace ABA
{
    // 内存对象池，为了不频繁GC
    public class Pool<T> : Singleton<Pool<T>> where T : new()
    {
        private List<T> m_objPool = new List<T>();
        private Func<T> _createCB;
        private Action<T> _destroyCB;

        public void InitPool(int count, Func<T> createCB = null, Action<T> destroyCB = null)
        {
            _createCB = createCB;
            _destroyCB = destroyCB;

            ClearPool();
            for (int i = 0; i < count; i++)
            {
                T newObj = CrreateObj();
                m_objPool.Add(newObj);
            }
        }

        T CrreateObj(){
            T newObj;
            if(_createCB != null){
                newObj = _createCB();
            }
            else{
                newObj = new T();
            }
            return newObj;
        }
        void DestroyObj(T obj){
            if(_destroyCB != null){
                _destroyCB(obj);
            }
        }

        // 得到实例
        public T Get()
        {
            return DoAlloc();
        }

        // 收回实例
        public void Put(T obj)
        {
            DoFree(obj);
        }

        private T DoAlloc()
        {
            T newObj;
            if (m_objPool.Count > 0)
            {
                var lastIndex = m_objPool.Count - 1;
                newObj = m_objPool[lastIndex];
                m_objPool.RemoveAt(lastIndex);
            }
            else
            {
                newObj = CrreateObj();
            }

            return newObj;
        }

        private void DoFree(T obj)
        {
            if (obj == null)
            {
                return;
            }

            m_objPool.Add(obj);
        }

        public void ClearPool()
        {
            for (int i = 0; i < m_objPool.Count; i++)
            {
                DestroyObj(m_objPool[i]);
            }
            m_objPool.Clear();
        }

        public string GetName()
        {
            return typeof(T).FullName;
        }

        // public List<T> GetPoolList()
        // {
        //     return m_objPool;
        // }

        public int GetPoolItemCount()
        {
            return m_objPool.Count;
        }
    }
}